package main

import (
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"strconv"
	"time"
)

type Transaction struct{
	//fromNode node
	sourceIP string
	disIP string
	sourcePort string
	disPort string
	data string
	transactionID int
	transactionHash []byte
	timestamp int64
}

var count = 0

func NewTransaction(srcIP, disIP, srcPort, disPort, data string)*Transaction{
	t := new(Transaction)
	t.data = data
	t.disIP = disIP
	t.disPort = disPort
	t.sourceIP = srcIP
	t.sourcePort = srcPort
	t.transactionID = count
	count += 1
	t.timestamp = time.Now().UnixNano()
	t.transactionHash = t.hashWorkMessage()
	return t
}

func (t Transaction) hashWorkMessage() []byte {
	message := t.sourceIP + t.sourcePort +
		t.disIP + t.disPort + t.data
	msgHash := sha256.Sum256([]byte(message))
	return msgHash[:]
}

func (t Transaction) traString() string {
	message:= "业务序列号" + strconv.Itoa(t.transactionID)+
		"\n业务hash" + hex.EncodeToString(t.transactionHash) +
		"\n 业务创建时间" + strconv.FormatInt(t.timestamp,10)
	return message
}

//节点加入
func (n node) TraJoin(t *Transaction)string{
	//获取证书信息和自签名
	nodeCert := n.nodeCert()
	decodeCert := new(Cert)
	err := json.Unmarshal([]byte(nodeCert), decodeCert)
	if err != nil{
		panic(err)
	}
	//生成源IP，目的IP，源端口，目的端口，请求包数据哈希值、自签名证书
	traQuest := new(traCert)
	traQuest.SrcIP = t.sourceIP
	traQuest.SrcPort = t.sourcePort
	traQuest.DisPort = t.disIP
	traQuest.DisPort = t.disPort
	dataHash := sha256.Sum256([]byte(t.data))
	traQuest.Hash = dataHash[:]
	Cm := new(NodeInfo)
	Cm.PublicKey = decodeCert.PublicKey
	Cm.Addr = decodeCert.Addr
	Cm.Mac = decodeCert.Mac
	Cm.EndTime = decodeCert.EndTime
	certInfo, err := json.Marshal(Cm)
	if err != nil{
		panic(err)
	}
	traQuest.CertInfo = certInfo
	traQuest.SignInfo = decodeCert.SignInfo
	//转为字符串
	jsonQuest, err := json.Marshal(traQuest)
	if err != nil {
		panic(err)
	}
	//转为字符串并返回值
	quest := string(jsonQuest)
	return quest
}

type traCert struct {
	SrcIP string
	DstIP string
	SrcPort string
	DisPort string
	Hash []byte
	CertInfo []byte
	SignInfo []byte
}

//验证新节点
func (n *node)VeriTra(cert string) int64{
	decodeCert := new(traCert)	//数据格式解码
	err := json.Unmarshal([]byte(cert), decodeCert)
	if err != nil{
		panic(err)
	}
	//log.Println(decodeCert)
	publicKey := n.rsaPubKey	//证书内信息获取
	certInfo := decodeCert.CertInfo
	signInfo := decodeCert.SignInfo
	digest := sha256.Sum256(certInfo)
	ans := n.RsaVerySignWithSha256(digest[:], signInfo, publicKey)//验证签名
	if ans == true {
		id := n.NewID()
		return id
	} else {
		panic("transaction verify error")
	}
}

//通过时间戳生成唯一序列号
func (n node)NewID () int64 {
	n.lock.Lock()	//数据锁，防止冲突
	ti := time.Now().UnixNano()//获取时间戳
	//s := strconv.FormatInt(ti,10)
	time.Sleep(time.Duration(1)*time.Nanosecond)//间隔1ns，防止时间戳重复
	n.lock.Unlock()
	//TODO
	//可以优化，获取唯一序列号
	return ti
}
